class EnyaraPlayerController extends PlayerController;

var int iStunTimeRemaining;
var bool bAlreadyStunned;
var bool bInvulnToStun;
var bool bUseStunTimer;
var bool bUseInvulnTimer;
var bool bMinigameMode;

var vector PlayerMouse;   //2D vector of mouse cursor location on screen
var vector PlayerMouse3D; //3D vector of mouse cursor location on screen
var vector ScreenLocation, WorldLocation, mtLoc;
var vector HitLocation, HitNormal, OldHitLocation, OldHitNormal;
var actor HitActor, OldHitActor;
var LevelInfo LevelActor;
var float LastHUDSizeX;   //Find current screen width
var float LastHUDSizeY;   //Find current screen height
var float XPos,YPos;
var bool RightMouseHeld;      //bool is true when right mouse button held, false otherwise
var bool toRotate; //bool is true when player left clicks
var string s;
var int Mana, ManaMax, SuperManaMax;
var float timeQueue;
var bool usingMana; //bool returns true if the player is curently using their mana
var bool unlimitedMana; //when true, unlimited mana has been activated
//variables from MyPlayerController (brian)
var LevObject L;
var bool bHasInteraction;
var LevManager LManager;
var LevObject DebugPointer;
var float TickCount, tickskip; //are these needed?

var interaction interactionEnyaraMouse;
var interaction interactionRightMouse;
var interaction interactionMenu;
var interaction interactionMy;

var bool isTargeting; //True when in targeting mode

/*******************

    MINIGAME STUFF

*******************/

var bool           HasInteractionEnabled;
var interaction    PlayerInteraction;

// Handle "death"
var bool           DeathCountdown;       // Did they "die"?  Then true
var float          DeathTimer;           // How much time left until respawning?
var float          DeathTimerStart;      // The time until "death" in seconds

// Pawn movement parameters
var rotator        DesiredPlayerRotation;
var rotator        ActualPlayerRotation;
var vector         DesiredPlayerLocation;
var vector         UseDesiredPlayerLocation; // Really just bools; 1 to use X, Y, or Z ... 0 otherwise
var float          ActualPlayerPropel;   // Our target is the player propel factor
var float          PlayerPropelFactor;   // A constant that determines how fast a value of "1" propels them
var vector         PlayerAcceleration;   // Independent of Pawn.Acceleration
var vector         PlayerVelocity;       // Independent of Pawn.Velocity
var rotator        PlayerRotation;       // Independent of Pawn.Rotation

// Camera movement parameters
var vector         ActualCameraLocation;
var float          CameraDistanceFactor; // A constant that determines how far away from the player a value of "1" will set the camera
var float          ActualCameraDistance;
var float          DesiredCameraDistance;

// Camera rotation parameters
var rotator        DesiredCameraRotation;
var rotator        ActualCameraRotation;
var bool           LastRotationHasEnded;
var rotator        CameraRotationSpeed;
var float          CameraRotationMaximumSpeed;
var rotator        CameraRotationAcceleration;
var float          CameraRotationAccelerationFactor;
var float          CameraRotationSlowdownDistance;
var float          CameraRotationSizePerTick;
var float          CameraTimeInVolume;

// Miscellaneous
var MinigameFlyingVolume CurrentFlyingVolume;  // The flying volume the player's currently in
var EffectSparkleTrail SparkleTrail;
var EffectAirDebris AirDebris;
var MinigamePlayerStart CurrentMinigamePlayerStart;
var EnyaraPawn PreMinigameEnyaraPawn;


function PostBeginPlay()
{
   super.PostBeginPlay();
//   Level.Game.ChangeTeam(self, 2, true);

   //instantiate LManager for the first time...
   self.LManager = Spawn(class'LevManager', self);
   LManager.InitUnused();
}

function SetPawnClass(string inClass, string inCharacter)
{
 super.SetPawnClass("Enyara.EnyaraPawn", inCharacter);
}

function EnterStartState()
{
    super.EnterStartState();

    // Add our new interactions.
    interactionRightMouse = Player.InteractionMaster.AddInteraction("Enyara.RightMouseInteraction", Player);
    //Player.InteractionMaster.AddInteraction("Enyara.LeftMouseInteraction", Player);
    interactionEnyaraMouse = Player.InteractionMaster.AddInteraction("Enyara.EnyaraMouseInteraction", Player);
    interactionMenu = Player.InteractionMaster.AddInteraction("Enyara.MenuInteraction", Player);

    //lev interaction class
    if ((Viewport(Player) != None) && (!bHasInteraction))
    {
        interactionMy = Player.InteractionMaster.AddInteraction("Enyara.MyInteraction", Player);
        bHasInteraction = true;
    }

}

function useMana(int manaUsed)
{
   if(!unlimitedMana) {
      if (Mana >= manaUsed){
         Mana -= manaUsed;
         usingMana=true;
      }
      else
         ClientMessage("Not Enough Mana", 'CriticalEvent');
   }
}

function drainMana(int manaDrained)
{
   if(!unlimitedMana) {
      if (Mana >= manaDrained)
         Mana -= manaDrained;
      else
         Mana = 0;

   }
}

function bool restoreMana(int manaRestored, int restoreMax)
{
//restoreMax allows restoration above the normal max, eg if you want
//to use a max mana boost power up

   if(ManaMax < restoreMax)
      ManaMax = restoreMax;
   if ( Mana < restoreMax){
      Mana = Min(restoreMax, Mana + manaRestored);
      return true;
   }

   return false;
}

state Stunned
{
   ignores TakeDamage;

   function BeginState()
   {
      if (!bAlreadyStunned && !bInvulnToStun) {
       ClientMessage("Stunned!",'CriticalEvent');
       Pawn.GroundSpeed = 0.0;
       Pawn.ShouldCrouch(true);

       bAlreadyStunned = true;
       bInvulnToStun = false;

       bUseStunTimer = true;
       bUseInvulnTimer = false;
       SetTimer(5.0, false);

       Pawn.bNoWeaponFiring = true;
      } else {
        GotoState('PlayerMousing');
      }
   }

   function EndState()
   {
      if ( Pawn != none ) {
        Pawn.JumpOffPawn();
        Pawn.bNoWeaponFiring = false;
      }

      GotoState('PlayerMousing');
   }
}

function Timer()
{
   //super.Timer();

   if (bUseStunTimer) {    //Check to see if player is stunned before you unstun them.
      ClientMessage("You are no longer stunned.",'CriticalEvent');
      SetTimer(5.0, false);  // Start timer for invuln
      bAlreadyStunned = false;
      bInvulnToStun = true;
      Pawn.GroundSpeed = 440.0;

      bUseStunTimer = false;
      bUseInvulnTimer = true;
      //self.Pawn.JumpOffPawn();
      GotoState('PlayerMousing');
   } else if (bUseInvulnTimer) {   // Make sure player isn't constantly stunned
      ClientMessage("You are no longer invulnurable to stun", 'CriticalEvent');
      bInvulnToStun = false;
      GotoState('PlayerMousing');
   }
}

function bool getRightMouse()
{
   if(RightMouseHeld)
      return true;
   else
      return false;
}

function vector getPlayerMouse3D()
{
   return PlayerMouse3D;
}

function setPlayerMouse3D(vector new3DVector)
{
   PlayerMouse3D = new3DVector;
}

function toggleRightMouseTrue()
{
   RightMouseHeld = true;
}

function toggleRightMouseFalse()
{
   RightMouseHeld = false;
}


function exec clearLines()
{
   clearstayingdebuglines();

}

//Trace the mouse cursor and return object/location hit
function doCursorTrace(out vector HitLoc, out vector HitNorm, out actor HitAct)
{
   local vector dir,end,camLoc;
   local rotator camRot;
   local float FOV, FOVdist;
   local actor ViewOwner;


   camRot = GetViewRotation();
   camLoc = vect(0,0,0);

   PlayerCalcView(ViewOwner,camLoc,camRot);
   //calcbehindview(camLoc,camRot,cameradist);


   FOV = (FovAngle/2)*Pi/180.00;
   FOVdist = (LastHUDSizeX/2)/Tan(FOV);

   dir.X = FOVdist;
   dir.Y = PlayerMouse.X - (LastHUDSizeX/2);
   dir.Z = -(PlayerMouse.Y - (LastHUDSizeY/2));

   dir = dir >> camRot;

   end = (camLoc) + Normal(dir)*10000;
   HitAct = Trace(HitLoc,HitNorm,end,camLoc,true);
   HitLoc.Z -= 40;
}

event PlayerTick( float DeltaTime ) {

    local float MagicCameraSlowdownNumber;
    local rotator CameraTravelDistance;
    local vector TempLocation;
    local float recoverTime;

   local xPawn targetPawn;
   Super.PlayerTick(DeltaTime);

   /****************************************************************************
    ** MINIGAME MODE **
   *****************************************************************************/

   if (bMinigameMode) {
       if (DeathCountdown) {
            // if the player's been hit, countdown until they respawn at the beginning
            // so disable player movement
            LastRotationHasEnded = false;
            SparkleTrail.Kill();
            ClientMessage("Death Timer:"@DeathTimer);
            if (DeathTimer > 0) {
                if (HasInteractionEnabled) {
                    Pawn.SetDrawType(DT_None);
                    Spawn(class'Enyara.EffectPetExplosion',,,Pawn.Location);
                    Player.InteractionMaster.RemoveInteraction(PlayerInteraction);
                    HasInteractionEnabled = false;
                }
                DeathTimer -= DeltaTime;
            } else {
                AirDebris.Kill();
                DeathCountdown = false;
                Pawn.SetLocation(CurrentMinigamePlayerStart.Location);
                PlayerVelocity = vect(0,0,0);
                PlayerAcceleration = vect(0,0,0);
                Pawn.SetPhysics(PHYS_None);
                Pawn.Acceleration = vect(0,0,0);
                Pawn.Velocity = vect(0,0,0);
            }
            return;
        } else {
            if (!HasInteractionEnabled) {
                Pawn.SetDrawType(DT_Mesh);
                PlayerInteraction = Player.InteractionMaster.AddInteraction("Enyara.MinigamePlayerInteraction", Player);
                Player.InteractionMaster.RemoveInteraction(interactionMy);
                Player.InteractionMaster.RemoveInteraction(interactionEnyaraMouse);
                Player.InteractionMaster.RemoveInteraction(interactionRightMouse);
                Player.InteractionMaster.RemoveInteraction(interactionMenu);
                HasInteractionEnabled = true;
                bHasInteraction = false;
            }
            if (Pawn.Physics != PHYS_Flying) {
               ActualPlayerRotation = rot(0,0,0);
               ActualCameraRotation = rot(0,0,0);
               ActualCameraLocation = Pawn.Location;
               Pawn.SetPhysics(PHYS_Flying);
               Pawn.AirSpeed = 1024;

               // Now attach some emitter effects.  First, the sparkle trail
               SparkleTrail = Spawn (class'Enyara.EffectSparkleTrail',,,Pawn.Location);
               SparkleTrail.SetBase (Pawn);

               // Then, the air debris
               AirDebris = Spawn (class'EffectAirDebris',,,Pawn.Location);
               AirDebris.SetBase (Pawn);
            }
            if (Pawn.PhysicsVolume.class!=class'MinigameFlyingVolume') {
                //PlayerKill();
                //ClientMessage("NOOOOOOOOOOO");
            }
        }

        // Update player velocity/location

        if (UseDesiredPlayerLocation != vect(0,0,0)) {

            TempLocation = Pawn.Location;
            if (UseDesiredPlayerLocation.X > 0) {
                PlayerAcceleration.X = 0;
                TempLocation.X += (DesiredPlayerLocation.X - TempLocation.X) * 2 * DeltaTime;
            }
            if (UseDesiredPlayerLocation.Y > 0) {
                PlayerAcceleration.Y = 0;
                TempLocation.Y += (DesiredPlayerLocation.Y - TempLocation.Y) * 2 * DeltaTime;
            }
            if (UseDesiredPlayerLocation.Z > 0) {
                PlayerAcceleration.Z = 0;
                TempLocation.Z += (DesiredPlayerLocation.Z - TempLocation.Z) * 2 * DeltaTime;
            }
            Pawn.SetLocation(TempLocation);

        }

        ActualPlayerPropel += (PlayerPropelFactor - ActualPlayerPropel) * 3 * DeltaTime;


        if (PlayerAcceleration == vect(0, 0, 0)) {
           // If they aren't hitting a key, start deteriorating their velocity
           PlayerVelocity *= 1 - (3 * DeltaTime);
        } else {
           // They ARE hitting a key, so add the acceleration to their velocity
           PlayerVelocity += PlayerAcceleration * (1024 * DeltaTime);
           PlayerVelocity = VClamp (PlayerVelocity, 0, Pawn.AirSpeed);
        }

        // Update player rotation

        ActualPlayerRotation += (DesiredPlayerRotation - ActualPlayerRotation) * 2 * DeltaTime;
        Pawn.SetRotation(ActualPlayerRotation);

        // Update camera rotation

        CameraTravelDistance = DesiredCameraRotation - ActualCameraRotation;
        CameraRotationAcceleration = RClamp(CameraTravelDistance, 0, 2);
        MagicCameraSlowdownNumber = FClamp (RSize(CameraTravelDistance) * CameraRotationMaximumSpeed / CameraRotationSlowdownDistance, 0, CameraRotationMaximumSpeed);

        if (RSize(CameraTravelDistance) < 16 || CameraTimeInVolume > 4) {
            // If they're close enough, snap 'em into place!
            ActualCameraRotation = DesiredCameraRotation;
            CameraRotationAcceleration = rot(0,0,0);
            CameraRotationSpeed = rot(0,0,0);
            CameraTimeInVolume = 0;
        } else {
            if (LastRotationHasEnded) {
                // if the camera's still now ...
                CameraRotationSpeed += CameraRotationAcceleration;
                CameraRotationSpeed = RClamp (CameraRotationSpeed, 0, MagicCameraSlowdownNumber);
                ActualCameraRotation += CameraRotationSpeed * 256 * DeltaTime;
                CameraTimeInVolume += DeltaTime;
            } else {
                // If the player switched volumes really fast (so that there will be two competing
                // rotational velocities), just stop the first rotation and move on to the new one
                if (RSize(CameraRotationSpeed) < 1) {
                    CameraRotationAcceleration = rot(0,0,0);
                    CameraRotationSpeed = rot(0,0,0);
                    LastRotationHasEnded = true;
                } else {
                    CameraRotationSpeed = CameraRotationSpeed * 0.5 * DeltaTime;
                }
            }
        }

        // Update camera location

        ActualCameraLocation += (Pawn.Location - ActualCameraLocation) * 8 * DeltaTime;
        ActualCameraDistance += (DesiredCameraDistance - ActualCameraDistance) * 2 * DeltaTime;

        if (DeathCountdown == true) {
            // If they "died," then disable movement
            Pawn.Velocity = vect(0,0,0);
        } else {
            // If they're with us, update the pawn's velocity
            Pawn.Velocity = (ActualPlayerPropel * CurrentFlyingVolume.PlayerVelocity + PlayerVelocity) >> ActualPlayerRotation;
        }

       return;
   }

   /****************************************************************************
    ** END MINIGAME MODE **
   *****************************************************************************/

   if(Mana==0)
      ClientMessage("Out Of Mana", 'CriticalEvent');
   if(usingMana) {
      usingMana=false;
      timeQueue=0;
   }
   else {
      timeQueue += DeltaTime;
      if(Pawn != None && Pawn.bIsCrouched)
         recoverTime=1.5;
      else
         recoverTime=3;
      if(timeQueue > recoverTime) {
         if(restoreMana(5,ManaMax)) //the player regenerates 5 mana every 3 seconds while not using mana
         timeQueue=0;
      }

   }

   doCursorTrace(HitLocation, HitNormal, HitActor);
   /*
   s = ""@HitActor.Name;

   ClientMessage("HitActor = "@HitActor.Name);
   ClientMessage("OldHitActor = "@OldHitActor.name);
   */

   if(HitActor != None && Pawn != none)
      Pawn.SetRotation(rotator(HitLocation-Pawn.Location));
   /*
   foreach AllActors(class'LevelInfo', LevelActor) {
      //ClientMessage("LevelActor ="@LevelActor.Name);
      if(HitActor != LevelActor) {
         OldHitLocation = HitLocation;
         OldHitNormal = HitNormal;
         OldHitActor = HitActor;
         //if(Pawn.Velocity==vect(0,0,0))
            Pawn.SetRotation(rotator(HitLocation-Pawn.Location));
      }


      else {
         foreach AllActors(class'xPawn', targetPawn) {
            if(OldHitActor == targetPawn &&  LineOfSightTo(targetPawn))
               if(targetPawn.Health > 0)
                  Pawn.SetRotation(rotator(targetPawn.Location-Pawn.Location));

         }



      }

   }*/


}


   /****************************************************************************
    ** MINIGAME MODE **
   *****************************************************************************/

function bool CleanUpMinigameEmitters () {

    SparkleTrail.Kill();
    AirDebris.Kill();

    interactionRightMouse = Player.InteractionMaster.AddInteraction("Enyara.RightMouseInteraction", Player);
    //Player.InteractionMaster.AddInteraction("Enyara.LeftMouseInteraction", Player);
    interactionEnyaraMouse = Player.InteractionMaster.AddInteraction("Enyara.EnyaraMouseInteraction", Player);
    interactionMenu = Player.InteractionMaster.AddInteraction("Enyara.MenuInteraction", Player);

    //lev interaction class
    if ((Viewport(Player) != None) && (!bHasInteraction))
    {
        interactionMy = Player.InteractionMaster.AddInteraction("Enyara.MyInteraction", Player);
        bHasInteraction = true;
    }

    return true;
}

   /****************************************************************************
    ** END MINIGAME MODE **
   *****************************************************************************/

function bool PlayerKill () {

    if (CurrentFlyingVolume.Invincibility || DeathCountdown == true)
    return false;

    DeathTimer = DeathTimerStart;
    DeathCountdown = true;
    return true;
}

function rotator RClamp (rotator r, float min, float max) {

    local float size;
    size = RSize(r);

    if (size > max) return r * max / size;
    if (size < min) return r * min / size;
    return r;

}

function vector VClamp (vector v, float min, float max) {

    local float size;
    size = VSize(v);

    if (size > max) return v * max / size;
    if (size < min) return v * min / size;
    return v;

}

function float RSize (rotator r) {
   return sqrt(square(r.Pitch)+square(r.Yaw)+square(r.Roll));
}

static function quat RotateQuat (quat q, rotator r) {

    local quat tempQuat;

    // Roll
    tempQuat = QuatFromAxisAndAngle( vect(1,0,0), 1.57085331 / 16384 * r.Roll );
    q = QuatProduct(q, tempQuat);

    // Yaw
    tempQuat = QuatFromAxisAndAngle( vect(0,0,1), 1.57085331 / 16384 * r.Yaw );
    q = QuatProduct(q, tempQuat);

    // Pitch
    tempQuat = QuatFromAxisAndAngle( vect(0,1,0), 1.57085331 / 16384 * r.Pitch );
    q = QuatProduct(q, tempQuat);

    return q;

}

simulated event PlayerCalcView(out actor ViewActor, out vector CameraLocation, out rotator CameraRotation )
{

    if (bMinigameMode) {

       /****************************************************************************
        ** MINIGAME MODE **
       *****************************************************************************/

        ViewActor = Self;
        bBehindView = true;

        CameraLocation = ActualCameraLocation - vector(ActualCameraRotation) * ActualCameraDistance * CameraDistanceFactor; // - vector(CameraTravelRotation) * CameraTravelDistance * CameraDistanceFactor;
        CameraRotation = ActualCameraRotation;

       /****************************************************************************
        ** END MINIGAME MODE **
       *****************************************************************************/

    } else {

        super.PlayerCalcView(ViewActor,CameraLocation,CameraRotation);

    }

}

function changeRot(rotator newRot) {
   Pawn.SetRotation(newRot);
}

auto state PlayerMousing
{
ignores SeePlayer, HearNoise, Bump;

    function bool NotifyPhysicsVolumeChange( PhysicsVolume NewVolume )
    {
        if ( NewVolume.bWaterVolume )
            GotoState(Pawn.WaterMovementState);
        return false;
    }

    function ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot)
    {
        local vector OldAccel;
        local bool OldCrouch;

        if ( Pawn == None )
            return;
        OldAccel = Pawn.Acceleration;
        if ( Pawn.Acceleration != NewAccel )
            Pawn.Acceleration = NewAccel;
        if ( bDoubleJump && (bUpdating || Pawn.CanDoubleJump()) )
            Pawn.DoDoubleJump(bUpdating);
        else if ( bPressedJump )
            Pawn.DoJump(bUpdating);

        Pawn.SetViewPitch(Rotation.Pitch);

        if ( Pawn.Physics != PHYS_Falling )
        {
            OldCrouch = Pawn.bWantsToCrouch;
            if (bDuck == 0)
                Pawn.ShouldCrouch(false);
            else if ( Pawn.bCanCrouch )
                Pawn.ShouldCrouch(true);
        }
    }

    function PlayerMove( float DeltaTime )
    {
        local vector X,Y,Z, NewAccel;
        local eDoubleClickDir DoubleClickMove;
        local rotator OldRotation, ViewRotation;
        local bool  bSaveJump;

        local vector MouseV, ScreenV;


        if( Pawn == None )
        {
            GotoState('Dead'); // this was causing instant respawns in mp games
            return;
        }

        GetAxes(CalcViewRotation,X,Y,Z);

        // Update acceleration.
        NewAccel = aForward*X + aStrafe*Y;
        NewAccel.Z = 0;
        if ( VSize(NewAccel) < 1.0 )
            NewAccel = vect(0,0,0);
        //DoubleClickMove = PlayerInput.CheckForDoubleClickMove(1.1*DeltaTime/Level.TimeDilation);

        GroundPitch = 0;
        ViewRotation = Rotation;
        if ( Pawn.Physics == PHYS_Walking )
        {
            // tell pawn about any direction changes to give it a chance to play appropriate animation
            //if walking, look up/down stairs - unless player is rotating view
             if ( (bLook == 0)
                && (((Pawn.Acceleration != Vect(0,0,0)) && bSnapToLevel) || !bKeyboardLook) )
            {
                if ( bLookUpStairs || bSnapToLevel )
                {
                    GroundPitch = FindStairRotation(deltaTime);
                    ViewRotation.Pitch = GroundPitch;
                }
                else if ( bCenterView )
                {
                    ViewRotation.Pitch = ViewRotation.Pitch & 65535;
                    if (ViewRotation.Pitch > 32768)
                        ViewRotation.Pitch -= 65536;
                    ViewRotation.Pitch = ViewRotation.Pitch * (1 - 12 * FMin(0.0833, deltaTime));
                    if ( (Abs(ViewRotation.Pitch) < 250) && (ViewRotation.Pitch < 100) )
                        ViewRotation.Pitch = -249;
                }
            }
        }
        else
        {
            if ( !bKeyboardLook && (bLook == 0) && bCenterView )
            {
                ViewRotation.Pitch = ViewRotation.Pitch & 65535;
                if (ViewRotation.Pitch > 32768)
                    ViewRotation.Pitch -= 65536;
                ViewRotation.Pitch = ViewRotation.Pitch * (1 - 12 * FMin(0.0833, deltaTime));
                if ( (Abs(ViewRotation.Pitch) < 250) && (ViewRotation.Pitch < 100) )
                    ViewRotation.Pitch = -249;
            }
        }
        Pawn.CheckBob(DeltaTime, Y);

        // Update rotation.
        SetRotation(ViewRotation);
        OldRotation = Rotation;
        UpdateRotation(DeltaTime, 1);
        bDoubleJump = false;

        if ( bPressedJump && Pawn.CannotJumpNow() )
        {
            bSaveJump = true;
            bPressedJump = false;
        }
        else
            bSaveJump = false;

        if ( Role < ROLE_Authority ) // then save this move and replicate it
            ReplicateMove(DeltaTime, NewAccel, DoubleClickMove, OldRotation - Rotation);
        else
            ProcessMove(DeltaTime, NewAccel, DoubleClickMove, OldRotation - Rotation);
        bPressedJump = bSaveJump;

        //get new mouse position offset
        MouseV.X = DeltaTime * aMouseX / (InputClass.default.MouseSensitivity * DesiredFOV * 0.01111);
        MouseV.Y = DeltaTime * aMouseY / (InputClass.default.MouseSensitivity * DesiredFOV * -0.01111);

        //update mouse position
        PlayerMouse += MouseV;



        //convert mouse position to screen coordinates if screen size is correct
        if((LastHUDSizeX > 0) && (LastHUDSizeY > 0))
        {
           ScreenV.X = PlayerMouse.X + LastHUDSizeX * 0.5;
           ScreenV.Y = PlayerMouse.Y + LastHUDSizeY * 0.5;
           //use these coordinates to trace or check HUD elements, etc
        }

    }

    function BeginState()
    {
        DoubleClickDir = DCLICK_None;
        bPressedJump = false;
        GroundPitch = 0;
        if ( Pawn != None )
        {
            if ( Pawn.Mesh == None )
                Pawn.SetMesh();
            Pawn.ShouldCrouch(false);
            if (Pawn.Physics != PHYS_Falling && Pawn.Physics != PHYS_Karma) // FIXME HACK!!!
                Pawn.SetPhysics(PHYS_Walking);
        }
     }

    function EndState()
    {
        GroundPitch = 0;
        if ( Pawn != None && bDuck==0 )
            Pawn.ShouldCrouch(false);
    }

Begin:
}

//##################################################################//
//##        functions from MyPlayerController (brian)             ##//
//##################################################################//
//spawns LevObject
function LevObject SpawnLev(){
     local LevObject lo;
     local vector ploc;
     local rotator prot;

     ploc = self.Pawn.Location + vector(self.Pawn.Rotation) * 2000;
     prot = self.Pawn.Rotation;

     lo = Spawn(class'LevObject', , , ploc, prot );
     clientmessage("spawned lobject");
     log("spawned lobject");

     return lo;
}

//spawns dummy pawn hardcoded distance away on same z plane
function MyOtherPawn SpawnPawn(){
     local MyOtherPawn mop;
     local vector ploc;
     local rotator prot;

     ploc = self.Pawn.Location + vector(self.Pawn.Rotation) * 2000;
     prot = self.Pawn.Rotation;

     mop = Spawn(class'MyOtherPawn', self, , ploc, prot);
     clientmessage("spawned other pawn");
     log("spawned other pawn");

     return mop;
}

function Clone(int n){
     local array<class<MyOtherPawn> > clones;
     local int i;
     local vector ploc, sloc;
     local rotator prot, srot, tmprot;
     local int offset, angle;
     offset = 100;
     angle = 16384;
     prot = self.Pawn.Rotation;
     ploc = self.Pawn.Location;

     tmprot = rot(0, 0, 0);
     tmprot.Yaw = angle;


     srot = prot;


     for (i=0; i<n; i++){
        tmprot.Pitch = 0;
        tmprot.Yaw = angle;
        tmprot.Roll = 0;
        sloc = ploc + vector(prot + tmprot) * offset;
        Spawn(class'MyOtherPawn', self, , sloc, srot);
        clientmessage("spawned pawn"$i@"at loc"@sloc);
        angle = angle*-1;
        if ((i % 2) == 0)
           offset=offset+100;
     }
}

//****** has/get/set fxns for PlayerController's LevObject
/*############################################################################
  #                    START Lev Handler Functions                           #
  ############################################################################*/
function LevManager getLManager(){ return self.LManager; }

function bool hasL(){
     if (self.L == None) return false;
     else return true;
}
function LevObject getL() {
     if (self.hasL()) return L;
     else{
          log("ERROR: PlayerController.getL() called when there is no L");
          return None;
     }
}
function LevObject setL(LevObject L) {
     self.L = L;
     log("PlayerController.L has been set to"@L.Name);
     return L;
}

function unsetL(){
     self.L = none;
}
/*############################################################################
  #                    END   Lev Handler Functions                           #
  ############################################################################*/

//line of sight vector...unit vector pointing towards pawn
function vector LOSVector(){
     return vector(self.pawn.Rotation)*-1;
}

/******************* exec functions *********************************/
//spawn a new pawn and swap controll
exec function spawnswap(){
     local MyOtherPawn newpawn;
     local EnyaraPawn originalpawn;
     local EnyaraPlayerController MPC;

     MPC = self;
     originalpawn = EnyaraPawn(self.Pawn);
     newpawn = SpawnPawn();

     MPC.UnPossess();
     MPC.Possess(newpawn);
}

//spawn a new pawn and swap controll
exec function kagebunshin(int num){
     Clone(num);
}

//exec handler fxn for spawnlev
exec function lspawn(){
     /*L = SpawnLev();
     clientmessage("L set to"@L);
     log("L set to"@L);*/
     DebugPointer = SpawnLev();
}

exec function manaGod() {
   if(unlimitedMana)
      unlimitedMana=false;
   else
      unlimitedMana=true;
}

//################## END MyPlayerController fxns ###################//


//spawnswap trigger fxn
event Trigger(Actor aBroadcaster, Pawn pTriggerer){
    local MyOtherPawn newpawn;
    local EnyaraPawn originalpawn;
    local EnyaraPlayerController MPC;

    clientMessage("aBroadcaster name:"@aBroadcaster.name);
    clientMessage("aBroadcaster tag:"@aBroadcaster.Tag);
    clientMessage("pTriggerer name:"@pTriggerer.Name);


    //ClientMessage("Just Basic Trigger RECIEVED!!!");
   // ClientMessage("self.name: "@self.name@", pTriggerer.name: "@pTriggerer.name);
    //ClientMessage("pawn.name: "@pawn.name);

    //erm...i dont think this is a very good check...but i'm using it for the time being
    /*if (pawn.name == pTriggerer.name){

        if(pTriggerer != none && pTriggerer.Controller != none
            && PlayerController(pTriggerer.Controller) != none)
        {
           ClientMessage("MADE IT!!!!!!!!!");
           MPC = self;
           originalpawn = EnyaraPawn(self.Pawn);
           newpawn = SpawnPawn();

           MPC.UnPossess();
           MPC.Possess(newpawn);
        }
    }*/


}

defaultproperties
{
    MidGameMenuClass = "Enyara.EnyaraPause"
    PawnClass=Class'Enyara.EnyaraPawn'
    InputClass=class'Enyara.MageInput'
    bMinigameMode=false
    ManaMax=100.000000
    SuperManaMax=200.000000
    Mana = 100

    /*********************

        MINIGAME STUFF

    **********************/

    //InputClass = class'MinigamePlayerInput' // I had to make a new input class to disable traditional movement
    //PawnClass = class'Enyara.MinigamePawn'
    HasInteractionEnabled = false
    LastRotationHasEnded = true

    DeathTimer = 0;
    DeathTimerStart = 3;

    PlayerPropelFactor = 768;
    CameraDistanceFactor = 256;

    CameraRotationMaximumSpeed = 128;

}
